#include "BodyHttpRequest.h"
#include "EasyHttpLog.h"
#include "Kismet/KismetStringLibrary.h"


FBodyHttpRequest::FBodyHttpRequest()
	: FBaseHttpRequest()
	, mBeginRange(0)
	, mEndRange(0)
	, mRecvBytesThisRequest(0)
{

}

FBodyHttpRequest::~FBodyHttpRequest()
{

}

void FBodyHttpRequest::Initilize(int32 ID, const FString &Url, int32 BeginRange, int32 EndRange, const FString &LastModify)
{
	FBaseHttpRequest::BaseInitilize(ID, Url);
	mBeginRange = BeginRange;
	mEndRange = EndRange;
	mLastModify = LastModify;
}

const TArray<uint8>* FBodyHttpRequest::GetData() const
{
	return &mContentData;
}

void FBodyHttpRequest::InitHeader()
{
	m_pRequest->SetURL(m_Url);
	m_pRequest->SetVerb(TEXT("GET"));

	FString StrRange = TEXT("bytes=") + FString::FromInt(mBeginRange+ mContentData.Num()) + TEXT("-") + FString::FromInt(mEndRange);
	m_pRequest->SetHeader(TEXT("Range"), StrRange);

	m_pRequest->SetHeader(TEXT("If-Range"), mLastModify);
}

void FBodyHttpRequest::UpdateStage(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bConnectedSuccessfully)
{
	FBaseHttpRequest::UpdateStage(Request, Response, bConnectedSuccessfully);
	RecordDetailLogf(Response.IsValid(), "Index:%d, ResponseCode:%d", m_nUinqueID, Response->GetResponseCode());
	if (m_eStage == EHttpRequestStage::eStage_Succeed)
	{
		if (Response->GetResponseCode() == 206)
		{
			m_eStage = EHttpRequestStage::eStage_Succeed;
		}
		else if (Response->GetResponseCode() == 200)
		{
			m_eStage = EHttpRequestStage::eStage_OutOfDate;
		}
	}
}

int32 FBodyHttpRequest::GetRecvBytes() const
{
	return mContentData.Num()+mRecvBytesThisRequest;
}

bool FBodyHttpRequest::CanRetry() const
{
	return FBaseHttpRequest::CanRetry() && GetRemainBytes()>0;
}

bool FBodyHttpRequest::Retry()
{
	// FixBodyStage();
	bool bRetry = FBaseHttpRequest::Retry();
	RecordDetailLog("index:%d, bRetry:%s", m_nUinqueID, *UKismetStringLibrary::Conv_BoolToString(bRetry));
	return bRetry;
}

bool FBodyHttpRequest::NeedDeserialized() const
{
	return m_eStage!=EHttpRequestStage::eStage_None;
}

void FBodyHttpRequest::Serialized(FMemoryWriter &Writer)
{
	int32 stage = (int32)m_eStage;
	Writer << stage;
	Writer << mBeginRange;
	Writer << mEndRange;
	Writer << mContentData;
}

void FBodyHttpRequest::Deserialized(FBufferReader &Reader)
{
	int32 stage;
	Reader << stage;
	m_eStage = (EHttpRequestStage::Type)stage;
	Reader << mBeginRange;
	Reader << mEndRange;
	Reader << mContentData;
}

void FBodyHttpRequest::SetLastModify(const FString &LastModify)
{
	mLastModify = LastModify;
}

void FBodyHttpRequest::CompleteCallback(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bConnectedSuccessfully)
{
	if (Response.IsValid())
	{
		RecordDetailLog("Url:%s, Range:%d-%d, PreRecvBytes:%d, This Request RecvBytes:%d, TotalRecvBtyes:%d", 
			*m_Url, mBeginRange, mEndRange, mContentData.Num(), Response->GetContent().Num(), mContentData.Num() + Response->GetContent().Num());
		mContentData.Append(Response->GetContent());
		mRecvBytesThisRequest = 0;
	}

	FBaseHttpRequest::CompleteCallback(Request, Response, bConnectedSuccessfully);
}

void FBodyHttpRequest::HeaderReceivedCallback(FHttpRequestPtr Request, const FString& HeaderName, const FString& NewHeaderValue)
{
	FBaseHttpRequest::HeaderReceivedCallback(Request, HeaderName, NewHeaderValue);
}

void FBodyHttpRequest::ProgressCallback(FHttpRequestPtr Request, int32 BytesSent, int32 BytesReceived)
{
	mRecvBytesThisRequest = BytesReceived;
	FBaseHttpRequest::ProgressCallback(Request, BytesSent, BytesReceived);
}

void FBodyHttpRequest::WillRetryCallback(FHttpRequestPtr Request, FHttpResponsePtr Response, float SecondsToRetry)
{
	FBaseHttpRequest::WillRetryCallback(Request, Response, SecondsToRetry);
}

int32 FBodyHttpRequest::GetRemainBytes() const
{
	return mEndRange - mBeginRange - mContentData.Num();
}

void FBodyHttpRequest::FixBodyStage()
{
	int32 remainBytes = GetRemainBytes();
	if (remainBytes == 0)
	{
		RecordDetailLogf(m_eStage==EHttpRequestStage::eStage_Succeed, 
			"Index:%d, Range:%d-%d, RecvBtyes:%d, RemainBtyes:%d, Stage:%s",
			m_nUinqueID, mBeginRange, mEndRange, GetRecvBytes(), GetRemainBytes(), EHttpRequestStage::ToString(m_eStage));
		m_eStage = EHttpRequestStage::eStage_Succeed;
	}
	else if (remainBytes<0)
	{
		RecordDetailLog("Index:%d, Range:%d-%d, RecvBtyes:%d, RemainBtyes:%d, Stage:%s",
			m_nUinqueID, mBeginRange, mEndRange, GetRecvBytes(), GetRemainBytes(), EHttpRequestStage::ToString(m_eStage));

		m_eStage = EHttpRequestStage::eStage_Failed;
		mContentData.Empty();
		mRecvBytesThisRequest = 0;
	}
}
